package com.neusoft.databus.agent.pool.opc;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

import org.apache.commons.pool2.PooledObject;
import org.openscada.opc.lib.common.AlreadyConnectedException;
import org.openscada.opc.lib.common.ConnectionInformation;
import org.openscada.opc.lib.da.Server;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import com.neusoft.databus.common.connection.OpcConnection;
import com.neusoft.databus.common.exception.DisconnectException;
import com.neusoft.databus.common.pool.AbstractPoolFactory;

import lombok.extern.slf4j.Slf4j;

/**
 * OPC连接工厂类
 *
 * @author naxiang
 */
@Slf4j
@Component
public class OpcFactory extends AbstractPoolFactory<OpcConnection, Server> {

    @Override
    public Server create(final OpcConnection connection) throws Exception {

        if (OpcFactory.log.isInfoEnabled()) {
            OpcFactory.log.info("start to create opc connection, {}", connection.getHost());
        }

        final ConnectionInformation connectionInformation = new ConnectionInformation();
        if (!StringUtils.isEmpty(connection.getHost())) {
            connectionInformation.setHost(connection.getHost());
        }
        if (!StringUtils.isEmpty(connection.getDomain())) {
            connectionInformation.setDomain(connection.getDomain());
        }
        if (!StringUtils.isEmpty(connection.getUser())) {
            connectionInformation.setUser(connection.getUser());
        }
        if (!StringUtils.isEmpty(connection.getPassword())) {
            connectionInformation.setPassword(connection.getPassword());
        }
        if (!StringUtils.isEmpty(connection.getProgid())) {
            connectionInformation.setProgId(connection.getProgid());
        }
        if (!StringUtils.isEmpty(connection.getClsid())) {
            connectionInformation.setClsid(connection.getClsid());
        }
        final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
        final Server server = new Server(connectionInformation, scheduler);
        try {
            server.connect();
        } catch (final AlreadyConnectedException e) {
        } catch (final Exception e) {
            throw new DisconnectException(e.getMessage(), e);
        }
        return server;
    }

    @Override
    public void destroy(final Server v) {
        if (OpcFactory.log.isInfoEnabled()) {
            OpcFactory.log.info("destroy opc connection object from pool");
        }
        v.disconnect();
    }

    @Override
    public boolean validateObject(final OpcConnection connection, final PooledObject<Server> p) {
        final Server server = p.getObject();
        boolean validate = false;
        if (null != server.getServerState()) {
            validate = true;
        }
        return validate;
    }
}
